/*
 * MIT License
 * 
 * Copyright (c) 2017 wen.gu <454727014@qq.com>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/***************************************************************************
 * Name: vos_vfs_stdc.c
 *
 * Purpose: std c file operation interface
 *
 * Developer:
 *   wen.gu , 2015-10-13
 *
 * TODO: 
 *
 ***************************************************************************/

//inner header file
#include "sys_config.h"

#if defined(USE_STDC_FILE_INTERFACE) && USE_STDC_FILE_INTERFACE

//API header filed
#include "sys/vos_vfs.h"
#include "thread/vos_mutex.h"
#include "vos_error.h"

#include <stdio.h>
/***************************************************************************
*
* data struct define
*
***************************************************************************/

/***************************************************************************
*
* inner function define
*
***************************************************************************/
static const char* getFileOpenMode(vfs_open_mode_t mode)
{
    const char* opMode = NULL;
    switch (mode)
    {
    case VFS_MODE_R:    opMode = "rb";  break;
    case VFS_MODE_RW:   opMode = "rwb"; break;
    case VFS_MODE_WCA:  opMode = "ab";  break;
    case VFS_MODE_WCT:  opMode = "wb";  break;
    case VFS_MODE_RWCA: opMode = "ab+"; break;
    case VFS_MODE_RWCT: opMode = "wb+"; break;
    default:
        break;
    }

    return opMode;
}
/***************************************************************************
*
* API define
*
***************************************************************************/

GPHD vfsFileOpen(const char* name, vfs_open_mode_t mode)
{
    FILE* fp = NULL;
    if (name)
    {       
        const char* opMode = getFileOpenMode(mode);

        if (opMode)
        {

            fp = fopen(name, opMode);
        }
    }    

    return (GPHD)fp;
}

void vfsFileClose(GPHD fhd)
{
    if (fhd)
    {
        fclose(fhd);
    }
}

GS32 vfsFileRead(GPHD fhd, void* buf, GU32 size)
{
    if (fhd)
    {
        return fread(buf, 1, size, fhd);
    }

    return G_FAIL;    
}

GS32 vfsFileWrite(GPHD fhd, const void* buf, GU32 size)
{
    if (fhd)
    {
        return fwrite(buf, 1, size, fhd);
    }

    return G_FAIL; 
}



GS64 vfsFileSeek(GPHD fhd, GS64 offset, vfs_seek_mode_t whence)
{
    if (fhd)
    {
        int seekMode = 0;
        switch (whence)
        {
        case VFS_SEEK_SET: seekMode = SEEK_SET; break;
        case VFS_SEEK_CUR: seekMode = SEEK_CUR; break;
        case VFS_SEEK_END: seekMode = SEEK_END; break;
        default:
            goto EXIT;
            break;
        }

        if (fseek(fhd, offset, seekMode) == 0)
        {
            return ftell(fhd);
        }
    }
EXIT:
    return G_FAIL;
}

GS64 vfsFileTell(GPHD fhd)
{
    if (fhd)
    {
        return ftell(fhd);
    }

    return 0;
}

GS32 vfsFileSync(GPHD fhd)
{
    if (fhd)
    {
        if (fflush(fhd) == 0)
        {
            return G_OK;
        }
    }

    return G_FAIL;
}

GS64 vfsFileSize(GPHD fhd)
{
    if (fhd)
    {
        GS64 curPos = ftell(fhd);
        if (fseek(fhd, 0, SEEK_END) == 0)
        {
            
            GS64 size = ftell(fhd);

            if (fseek(fhd, curPos, SEEK_SET) == 0)
            {
                return size;
            }
        }
    }

    return 0;
}

#endif
